import React, { Component } from 'react'
// import SonClass from './components/SonClass'
import SonClass from './components/SonClass'
import SonFun from './components/SonFun'

/* 组件间通信的借助props传递

1. 父组件向子组件传递数据：

   - 父组件如何传递数据给子组件？
     - 通过子组件调用标签属性的方式传递

   - 子组件如何接收父组件传递的数据？

     1. 类子组件通过 this.props属性接收	
     2. 函数子组件通过函数的形参接收【一般会直接在参数位置解构】

2. 子组件向父组件传递数据，也是借助props

   1. 在父组件定义一个方法，方法设置一个或多个形参
   2. 将该方法改变this指向，让this指向当前组件的实例对象
   3. 将该方法通过标签数据性的方式传递给子组件
   4. 在子组件中通过 props接收
      1. 类组件： this.props.方法名
      2. 函数组件: props.方法名
   5. 在子组件中调用该方法，并将要传递的数据以实参的方式传递

注意：
    3,跨级传递数据，如爷孙组件，通过contextTypes来获取，
    使用时通过，this.context.属性名来使用
// 1. 创建 Context
首先，你需要使用 React.createContext 方法来创建一个 Context 对象。这个对象将被用来在组件树中传递数据
const MyContext = React.createContext(defaultValue);
import MyContext from './MyContext';

// 2,Provider 是 Context 对象的组件形式，它允许你为 Context 指定一个值，这个值会传递给所有嵌套的 Consumers。
<MyContext.Provider value={一些值}>
{children}
</MyContext.Provider>

// 3,Consumer 是 Context 对象的另一个组件形式，它订阅 Context 的值，并在值变化时重新渲染。
<MyContext.Consumer>
  {value =>  基于 value 渲染组件 }
  </MyContext.Consumer>
// 4, const value = useContext(MyContext);


为context提供值
import React, { useState } from 'react';

function App() {
  const [user, setUser] = useState(null);

  return (
    <MyContext.Provider value={{ user, setUser }}>
      <Navbar />
      <Sidebar />
      <Main />
    </MyContext.Provider>
  );
}
// 使用context的值
// 使用 Consumer
import React from 'react';

function Profile() {
  return (
    <MyContext.Consumer>
      {({ user, setUser }) => (
        <div>
          {user ? user.name : 'No user'}
        </div>
      )}
    </MyContext.Consumer>
  );
}

// 使用 useContext Hook
import React, { useContext } from 'react';

function Profile() {
  const { user, setUser } = useContext(MyContext);
  return (
    <div>
      {user ? user.name : 'No user'}
    </div>
  );
}

嵌套使用Provider
<MyContext.Provider value="primary">
  <AnotherContext.Provider value="secondary">
    <ChildComponent />
  </AnotherContext.Provider>vv
</MyContext.Provider>



1. props的children属性，可以接收到组件调用对标签中的子元素 */
export default class App extends Component {
  state = {
    count: 100,
    msg: 'hello'
  }
  addCount(num) {
    this.setState({
      count: this.state.count + num
    })
  
 
  }
  // 改变外部数据的方法
  changeCount(num) {
    this.setState({
      count: this.state.count -num
    })
  }
  decCount=(num)=> {
    this.setState({
      count: this.state.count -num
    })
  }
  render() {
    const {count } = this.state
    return (
      <div>
        <div>
          <h2>App组件: {count}</h2>
          <button onClick={()=>this.addCount(2)}>count++</button>
        </div>
        <h3>
        <SonClass num={count} name={'类组件通信'} decCount={this.decCount} changeCount={this.changeCount.bind(this)} ></SonClass>
        {/* 使用bind（this）函数/ 直接把函数做成一个箭头函数可以在子组件中进行传值，然后调用父组件中的函数 */}
        </h3>
        <h4>
        <SonFun msg={count} name={'函数组件通信'}  changeCount={this.changeCount.bind(this)}></SonFun>

        </h4>
      </div>
    )
  }
}
